# -*- coding: utf-8 -*-
#!/usr/bin/env python

from PyQt4.QtCore import *
from PyQt4.QtGui import *

import aimsmodel
import aimseditdlg

class AimsEdit(QWidget):

    NextId = 1

    def __init__(self, filename=QString(), parent=None):
        super(AimsEdit, self).__init__(parent)
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.filename = filename
        if self.filename.isEmpty():
            self.filename = QString("Unnamed-%d.xml" % AimsEdit.NextId)
            AimsEdit.NextId += 1
            self.treeWidget = aimsmodel.TreeOfTableWidget()
        else:
            self.load()

        # Поле, хранящее информацию о том, есть в
        # модели не сохранённые на диск изменения, или нет.
        self.modified = False
	
        self.setWindowTitle(QFileInfo(self.filename).fileName())

        self.resize(750, 450)

        layout = QVBoxLayout()
        layout.addWidget(self.treeWidget)

        # Разместим кнопки редактирования:
        addButton  = QPushButton("Add")
        editButton = QPushButton("Edit")
        delButton  = QPushButton("Delete")

        # ссылки на кнопки необходимо сохранить,
        # дабы иметь возможность запрещать её
        # использовать.
        self.addButton = addButton
        self.delButton = delButton

        buttonLayout = QHBoxLayout()
        buttonLayout.addStretch()

        buttonLayout.addWidget(addButton)
        buttonLayout.addWidget(editButton)
        buttonLayout.addWidget(delButton)

        layout.addLayout(buttonLayout)
        self.setLayout(layout)

        self.connect(addButton, SIGNAL("clicked()"), self.onAdd)
        self.connect(editButton, SIGNAL("clicked()"), self.onEdit)
        self.connect(delButton, SIGNAL("clicked()"), self.onDelete)

        self.connect(self.treeWidget, SIGNAL("activated"), self.activated)

    def activated(self):
        self.addButton.setEnabled(self.isAdditionAvalible())
        self.delButton.setEnabled(self.isDeletionAvalible())
        self.emit(SIGNAL("currentAimChanged"))

    def isDeletionAvalible(self):
        # удалять можно всё, кроме корневой цели дерева:
        currentParent = self.treeWidget.currentNode().parent
        return currentParent is not None and currentParent.parent is not None

    def isAdditionAvalible(self):
        # добавлять подцели можно только в сложные цели:
        return self.treeWidget.currentNode().isComplex()

    def isModified(self):
        return self.modified

    def setModified(self, _modified):
        self.modified = _modified

    def onAdd(self):
        # Обработчик нажатия кнопки Add
        dialog      = aimseditdlg.AimsEditDlg(self)
        fieldValues = dialog.getFieldValues()
        
        if fieldValues is not None:
            trueFields = []
            for field in fieldValues[2:]:
                trueFields.append(field)
            if fieldValues[0]:
                newNode = aimsmodel.treeoftable.Node(fieldValues[1], trueFields)
            else:
                newNode = aimsmodel.treeoftable.ComplexNode(fieldValues[1], trueFields)

            self.add2Selected(newNode)

    def onEdit(self):
        # Обработчик нажатия кнопки Edit
        selected    = self.treeWidget.currentNode()
        dialog      = aimseditdlg.AimsEditDlg(self, [selected.name] + selected.fields)
        fieldValues = dialog.getFieldValues()
        if fieldValues is not None:
            selected.name = fieldValues[1]
            for i in range(len(fieldValues) - 2):
                selected.fields[i] = fieldValues[i + 2]
            self.setModified(True)

    def onDelete(self):
        # Обработчик команды "удалить выделеную цель"
        # Команда может поступать:
        # 1) От кнопки "Delete".
        # 3) Как часть обработки команды cut 
        selected = self.treeWidget.currentIndex();
        model    = self.treeWidget.model()
        parent   = model.parent(selected)
        if parent != QModelIndex:
            parentNode = model.nodeFromIndex(parent)
            node       = self.treeWidget.currentNode()
            row        = parentNode.rowOfChild(self.treeWidget.currentNode())
            parentNode.delChild(node)
            model.reset()
            self.treeWidget.expandAll();
            self.treeWidget.expanded();
            self.setModified(True)

    def onCopy(self):
        # Обработчик команды copy
        # -----------------------------------
        # Выбрать текущую выделенную цель,
        # сериализовать её, сохранить в буфер
        # обмена.
        QApplication.clipboard().setText(aimsmodel.AimModel.serialize(self.treeWidget.currentNode()))

    def onCut(self):
        # Обработчик команды cut
        # -----------------------------------
        # 1) Скопировать.
        # 2) Удалить.

        self.onCopy()
        self.onDelete()

    def onPaste(self):
        # Обработчик комманды paste
        # ------------------------------------
        # Выбрать текущую выделеную цель,
        # десериализовать содержимое буфера обмена,
        # вставить в текущую выделенную.
        selected = self.treeWidget.currentNode()
        newNode = aimsmodel.AimModel.deserialize(QApplication.clipboard().text())
        self.add2Selected(newNode)

    def closeEvent(self, event):
        # Обработчик события "перед закрытием":
        # нужно предложить пользователю сохраниться, если
        # есть несохранённые изменения.
        try:
          if self.isModified():
              desigion = QMessageBox.warning(self, "Aims Editor -- do you want to save changes?",
                    "Some changes unsaved. Save them?",
                    QMessageBox.Yes|QMessageBox.No|QMessageBox.Cancel)
              if desigion == QMessageBox.Yes:
                  self.save()
              elif desigion == QMessageBox.Cancel:
                  event.ignore()
                  
        except IOError, e:
           if QMessageBox.warning(self, "Text Editor -- Save Error",
                    "Failed to save%s\nQuit anyway?" % \
                    "\n\t".join(failures),
                    QMessageBox.Yes|QMessageBox.No) == QMessageBox.No:
                event.ignore()

    def add2Selected(self, newNode):
        # Реализация добавления новой ветки в одну из существующих.
        self.treeWidget.currentNode().insertChild(newNode)
        self.treeWidget.expandAll();
        self.treeWidget.expanded();
        self.setModified(True)

    def save(self):
        filename = self.filename
        error    = None
        fh       = None
        try:
          fh = QFile(filename)
          if not fh.open(QIODevice.WriteOnly):
            raise IOError, unicode(fh.errorString())
          stream = QTextStream(fh)
          
          stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
          stream << "<Aims>\n"
          stream << aimsmodel.AimModel.serialize(self.treeWidget.model().root)
          stream << "</Aims>\n"

          self.setWindowTitle(QFileInfo(self.filename).fileName())

        finally:
          if fh is not None:
            fh.close()
            self.setModified(False)

    def load(self):
        exception = None
        try:
            self.treeWidget = aimsmodel.TreeOfTableWidget(self.filename)
        except (IOError, OSError), e:
            exception = e
        finally:
            if exception is not None:
                self.treeWidget = None
                raise exception
  
    def export2Pdf(self, printer):
        painter = QPainter()
        painter.begin(printer)
        try:
            interMovie = 30
            interPara = 7
            interLine = 0

            fontMainTitle = QFont("Sans", 22, 50, False)
            fontTitle     = QFont("Sans", 18, 50, False)
            fontText      = QFont("Sans", 12, 30, False)

            freeRect = printer.pageRect()

            def draw(getBoundingRect, drawFunc, inter = 0):
                freeRect.adjust(0, inter, 0, 0)
                rect = getBoundingRect()
                if rect.height() + freeRect.top() > freeRect.bottom():
                    printer.newPage();
                    freeRect.setTopLeft(printer.pageRect().topLeft())
                    freeRect.setBottomRight(printer.pageRect().bottomRight())
                    rect = getBoundingRect()
                drawFunc(rect)
                freeRect.adjust(0, rect.height(), 0, 0)

            def drawText(text, inter = 0, flags=int(Qt.AlignLeft) | int(Qt.AlignTop) | int(Qt.TextWordWrap)):
                draw(lambda: painter.fontMetrics().boundingRect(freeRect, flags, text),
                    lambda rect: painter.drawText(rect, flags, text),
                    inter)

            painter.setFont(fontMainTitle)

            def printNode(node, tab=""):
              if isinstance(node, aimsmodel.treeoftable.ComplexNode):
                for i in range(node.childrenCount()):
                  child = node.childAtRow(i)
                  drawText(tab + child.name + " " + child.field(aimsmodel.DEADLINE), flags = Qt.AlignLeft | Qt.AlignTop)
                  printNode(child, tab + "\t")
            
            printNode(self.treeWidget.model().root)
        finally:
            painter.end()